
import java.io.IOException;
import java.io.StreamTokenizer;
import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;

/**
 *
 * @author Éric Beaudry
 */
public class Parseur {

    public Monde monde;
    public Etat  etatInitial;
    public But   but;

    public void parse(StreamTokenizer stoken) throws IOException{
        monde = new Monde();

        stoken.wordChars('_', '_');


        if(stoken.nextToken() != StreamTokenizer.TT_WORD)
            throw new RuntimeException();
        if(!stoken.sval.equals("Locations") && !stoken.sval.equals("Emplacements"))
            throw new RuntimeException();
        if(stoken.nextToken() != '{')
            throw new RuntimeException();


        while(stoken.nextToken() != '}'){
            assert stoken.ttype == StreamTokenizer.TT_WORD;

            String name = stoken.sval;
            stoken.nextToken(); // number;
            assert stoken.ttype == StreamTokenizer.TT_NUMBER;
            double x = stoken.nval;
            stoken.nextToken(); // number;
            assert stoken.ttype == StreamTokenizer.TT_NUMBER;
            double y = stoken.nval;
            stoken.nextToken(); // ;
            assert stoken.ttype == ';';
            Emplacement location = new Emplacement(name, x, y);
            monde.emplacements.put(name, location);
        }

        stoken.nextToken();
        if(stoken.ttype == StreamTokenizer.TT_WORD &&
                (stoken.sval.equalsIgnoreCase("Links")) || (stoken.sval.equalsIgnoreCase("Routes"))){
            if(stoken.nextToken() != '{')
                throw new RuntimeException();
            while(stoken.nextToken() != '}'){
                assert stoken.ttype == StreamTokenizer.TT_WORD;
                String name1 = stoken.sval;
                stoken.nextToken();
                assert stoken.ttype == StreamTokenizer.TT_WORD;
                String name2 = stoken.sval;
                stoken.nextToken();
                if(stoken.ttype != ';'){
                    assert stoken.ttype == StreamTokenizer.TT_NUMBER;
                    double maxspeed = stoken.nval;
                    stoken.nextToken();
                }
                assert stoken.ttype == ';';
                Emplacement l1 = monde.emplacements.get(name1);
                if(l1 == null)
                    throw new RuntimeException();
                Emplacement l2 = monde.emplacements.get(name2);
                if(l2 == null)
                    throw new RuntimeException();
                l1.routes.add(new Route(l1, l2));
                l2.routes.add(new Route(l2, l1));
            }
        }


        etatInitial = new Etat(monde);

        if(stoken.nextToken() != StreamTokenizer.TT_WORD)
            throw new RuntimeException();
        if(!stoken.sval.equals("Robots") && !stoken.sval.equals("Camions"))
            throw new RuntimeException();
        if(stoken.nextToken() != '{')
            throw new RuntimeException();

        int nbCamion = 0;
        while(stoken.nextToken() != '}'){
            assert stoken.ttype == StreamTokenizer.TT_WORD;
            String robotname = stoken.sval;
            stoken.nextToken();
            assert stoken.ttype == StreamTokenizer.TT_WORD;
            String locname = stoken.sval;
            stoken.nextToken(); // ;
            assert stoken.ttype == ';';
            monde.nomCamion = robotname;
            etatInitial.positionCamion = monde.emplacements.get(locname);
            if(etatInitial.positionCamion == null)
                throw new RuntimeException();
            nbCamion++;
        }
        if(nbCamion>1){
            System.err.println("AVERTISSEMENT : seul le dernier camion sera utilisé.");
        }

        if(stoken.nextToken() != StreamTokenizer.TT_WORD)
            throw new RuntimeException();
        if(!stoken.sval.equals("Boxes") && !stoken.sval.equals("Colis"))
            throw new RuntimeException();
        if(stoken.nextToken() != '{')
            throw new RuntimeException();

        Vector<String> positionColis = new Vector();
        while(stoken.nextToken() != '}'){
            assert stoken.ttype == StreamTokenizer.TT_WORD;
            String boxname = stoken.sval;
            stoken.nextToken();
            assert stoken.ttype == StreamTokenizer.TT_WORD;
            String locname = stoken.sval;
            stoken.nextToken(); // ;
            assert stoken.ttype == ';';
            monde.nomColis.add(boxname);
            positionColis.add(locname);
        }
        int nbColis = positionColis.size();

        etatInitial.colisEstSurCamion = new boolean[nbColis];
        etatInitial.positionsColis = new Emplacement[nbColis];
        for(int i=0;i<positionColis.size();i++){
            if(positionColis.get(i).equals(monde.nomCamion)){
                etatInitial.colisEstSurCamion[i] = true;
                etatInitial.nbColisCharges++;
            }
            else{
                etatInitial.positionsColis[i] = monde.emplacements.get(positionColis.get(i));
                if(etatInitial.positionsColis[i] == null)
                    throw new RuntimeException();
            }
        }

        if(stoken.nextToken() != StreamTokenizer.TT_WORD)
            throw new RuntimeException();
        if(!stoken.sval.equals("Goal") && !stoken.sval.equals("But"))
            throw new RuntimeException();
        if(stoken.nextToken() != '{')
            throw new RuntimeException();

        stoken.nextToken();

        Map<String, Emplacement> destinations = new TreeMap();
        while(stoken.ttype != '}'){
            assert stoken.ttype == StreamTokenizer.TT_WORD;
            String boxname = stoken.sval;
            stoken.nextToken();
            assert stoken.ttype == StreamTokenizer.TT_WORD;
            String locname = stoken.sval;
            stoken.nextToken(); // ;
            if(stoken.ttype != ';')
                throw new RuntimeException();
            stoken.nextToken();
            Emplacement e = monde.emplacements.get(locname);
            if(e==null)
                throw new RuntimeException();
            destinations.put(boxname, e);
        }

        but = new But();
        but.destinationsColis = new Emplacement[nbColis];
        for(int i=0;i<nbColis;i++)
            but.destinationsColis[i] = destinations.get(monde.nomColis.get(i));

        
    }


    
}
